/*
  Copyright 2008 Google Inc.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#ifndef CSCONNECT_STRING_UTILS_H__
#define CSCONNECT_STRING_UTILS_H__

#include <cstring>
#include <cstdarg>
#include <map>
#include <string>
#include <vector>
#include <stdint.h>         // Integer types and macros.
#include <csconnect/common.h>
#include <csconnect/unicode_utils.h>

namespace csconnect {

/**
 * @defgroup StringUtilities String utilities
 * @ingroup Utilities
 * @{
 */

/**
 * Case sensitive string map.
 */
typedef std::map<std::string, std::string> StringMap;

struct CaseInsensitiveCharPtrComparator {
  bool operator()(const char* s1, const char* s2) const {
    return strcasecmp(s1, s2) < 0;
  }
};

struct CaseInsensitiveStringComparator {
  bool operator()(const std::string &s1, const std::string &s2) const {
    return strcasecmp(s1.c_str(), s2.c_str()) < 0;
  }
};

typedef std::map<std::string, std::string,
                 CaseInsensitiveStringComparator> CaseInsensitiveStringMap;

typedef std::vector<std::string> StringVector;

/**
 * Removes the starting and ending spaces from a string.
 */
std::string TrimString(const std::string &s);

/**
 * Converts a string into lowercase.
 * Note: Only converts ASCII chars.
 */
std::string ToLower(const std::string &s);

/**
 * Converts a string into uppercase.
 * Note: Only converts ASCII chars.
 */
std::string ToUpper(const std::string &s);

/**
 * Format data into a C++ string.
 */
std::string StringPrintf(const char *format, ...)
  // Tell the compiler to do printf format string checking.
  PRINTF_ATTRIBUTE(1,2);
std::string StringVPrintf(const char *format, va_list ap);

/**
 * Append result to a supplied string
 */
void StringAppendPrintf(std::string *dst, const char *format, ...)
  PRINTF_ATTRIBUTE(2,3);
void StringAppendVPrintf(std::string *dst, const char *format, va_list ap);

/**
 * Encode a string into a JavaScript string literal enclosed with the specified
 * quote char, by escaping special characters in the source string.
 */
std::string EncodeJavaScriptString(const UTF16Char *source, char quote);
std::string EncodeJavaScriptString(const std::string &source, char quote);

/**
 * Decode a JavaScript string literal (with the beginning and ending quotes).
 * Returns false if the source is invalid JavaScript string literal.
 */
bool DecodeJavaScriptString(const char *source, UTF16String *dest);
bool DecodeJavaScriptString(const char *source, std::string *dest);

/**
 * Convert a JSON string into a evaluate-able JavaScript script string.
 * Returns true if the string is a valid JSON string.
 * Supports extended JSON grammar for Date objects.
 */
bool ConvertJSONToJavaScript(const char *json, std::string *script);

/** Checks if a string has a specified prefix. */
bool StartWith(const char *string, const char *prefix);

/** Checks if a string has a specified prefix, ignoring the case. */
bool StartWithNoCase(const char *string, const char *prefix);

/** Checks if a string has a specified suffix. */
bool EndWith(const char *string, const char *suffix);

/** Checks if a string has a specified suffix, ignoring the case. */
bool EndWithNoCase(const char *string, const char *suffix);

/** @} */

} // namespace csconnect

#endif // CSCONNECT_STRING_UTILS_H__
